package com.lishem;

import com.lishem.pojo.User;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import sun.misc.Unsafe;

import java.io.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class CreateObjectDemo {

    public static void main(String[] args) throws Throwable {
        System.out.println("方式一：直接new");
        User user1 = new User();
        System.out.println(user1);
        System.out.println("方式二：反射");
        User user2 = (User)Class.forName("com.lishem.pojo.User").newInstance();
        System.out.println(user2);
        Constructor constructor = User.class.getConstructor();
        User user3 = (User) constructor.newInstance();
        System.out.println(user3);
        System.out.println("方式三：clone方法");
        User user4 = (User)user2.clone();
        System.out.println(user4);
        System.out.println("方式四：序列化");
        //Write Obj to File
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
            oos.writeObject(user1);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(oos);
        }
        //Read Obj from File
        File file = new File("tempFile");
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(file));
            User user5 = (User) ois.readObject();
            System.out.println(user5);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(ois);
            try {
                FileUtils.forceDelete(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("方式五：使用方法句柄");
        // 定义构造函数的方法句柄类型为void类型，无参数
        MethodType constructorType = MethodType.methodType(void.class);
        // 获取构造函数的方法句柄
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle constructorHandle = lookup.findConstructor(User.class, constructorType);
        // 使用方法句柄调用构造函数创建对象
        User user6 = (User) constructorHandle.invoke();
        System.out.println(user6);

        System.out.println("使用Unsafe分配内存");
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        // 获取User类的字段偏移量
        long nameOffset = unsafe.objectFieldOffset(User.class.getDeclaredField("name"));
        long ageOffset = unsafe.objectFieldOffset(User.class.getDeclaredField("age"));
        // 使用allocateInstance方法创建对象，不会调用构造函数
        User user7 = (User) unsafe.allocateInstance(User.class);
        // 使用putObject方法设置字段的值
        unsafe.putObject(user7, nameOffset, "Lishem");
        unsafe.putInt(user7, ageOffset, 30);
        System.out.println(user7);
    }
}

